﻿using EcoTourEduca.BingYourMaps.Models;
using EcoTourEduca.BingYourMaps.Services;
using EcoTourEduca.BingYourMaps.ViewModels;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Title.Models;
using Orchard.DisplayManagement;
using Orchard.Media.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EcoTourEduca.BingYourMaps.Drivers
{
    public class BingMapsAreaDriver : ContentPartDriver<BingMapsAreaPart>
    {
        private readonly IBingYourMapsService _service;
		private readonly IContentManager _content;
		private readonly IMediaService _mediaService;
		private readonly dynamic _shape;

        public BingMapsAreaDriver(IBingYourMapsService mapListService, IContentManager content, IMediaService mediaService, IShapeFactory shapeFactory)
		{
			_service = mapListService;
			_content = content;
			_mediaService = mediaService;
			_shape = shapeFactory;
		}

		protected override DriverResult Display(BingMapsAreaPart areaPart, string displayType, dynamic shapeHelper)
		{
			// Create list of content items
			var locationContent = _shape.List();
			var locationContentItems = 
                areaPart.BingMapsLocations
                .Select(t => t.As<ContentItem>()) // Inc all of them, even the ones that have HideMap = true
				.OrderBy(t => t.As<TitlePart>().Title);
            // TODO: Test this orderby clause is okay if the part has no TitlePart
			locationContent.AddRange
                (locationContentItems.Select(
                    location => _content.BuildDisplay(location, "Summary")
                )
            );

			return ContentShape("Parts_BingMapsArea",
								() => shapeHelper.Parts_BingMapsArea(
									CenterLongitude: areaPart.CenterLongitude,
									CenterLatitude: areaPart.CenterLatitude,
									MapWidth: areaPart.MapWidth,
									MapHeight: areaPart.MapHeight,
									MapZoom: areaPart.MapZoom,
									MapType: areaPart.MapType,
									MapIconFolder: GetIconFolder(),
									BingMapsLocations: areaPart.BingMapsLocations.Where(loc => !loc.HideMap), // We only show in the map items that shouldn't be hidden
									LocationsCount: areaPart.BingMapsLocations.Count(),
									BingMapsLocationContentItems: locationContent,
									Titles: GetTitles(areaPart)));
		}

		//GET
		protected override DriverResult Editor(BingMapsAreaPart areaPart, dynamic shapeHelper)
		{
			return ContentShape("Parts_BingMapsArea_Edit",
								() => shapeHelper.EditorTemplate(
                                        TemplateName: "Parts/BingMapsArea",
                                        Model: BuildEditorViewModel(areaPart),
                                        Prefix: Prefix));
		}

		//POST
		protected override DriverResult Editor(BingMapsAreaPart areaPart, IUpdateModel updater, dynamic shapeHelper)
		{
			updater.TryUpdateModel(areaPart, Prefix, null, null);

			// Get Center (Lat,Long) from model (required to work in cultures that use ',' in decimal numbers)
			var model = new EditBingMapsAreaViewModel();
			updater.TryUpdateModel(model, Prefix, new [] { "CenterLatitudeStr", "CenterLongitudeStr" }, null);
			areaPart.CenterLatitude = model.CenterLatitude;
			areaPart.CenterLongitude = model.CenterLongitude;

			return Editor(areaPart, shapeHelper);
		}

		private EditBingMapsAreaViewModel BuildEditorViewModel(BingMapsAreaPart areaPart)
		{
			var mapType = areaPart.MapType ?? _service.DefaultMapType;

			var editModel = new EditBingMapsAreaViewModel
			{
				CenterLatitudeStr = areaPart.CenterLatitude.ToInvariantCultureString(),
				CenterLongitudeStr = areaPart.CenterLongitude.ToInvariantCultureString(),
                FriendlyName = areaPart.FriendlyName,
				MapWidth = areaPart.MapWidth,
				MapHeight = (areaPart.MapHeight == 0) ? 
                   EditBingMapsAreaViewModel.DefaultMapHeight 
                   : areaPart.MapHeight,
				MapZoom = areaPart.MapZoom,
				MapType = mapType,
				MapTypeList = _service.CreateMapTypeList(mapType),
				BingMapsLocations = areaPart.BingMapsLocations,
				Titles = GetTitles(areaPart),
				PinIconsFolder = GetIconFolder()
			};

			return editModel;
		}

		private String GetIconFolder()
		{
			return _mediaService.GetPublicUrl(BingYourMapsService.MAPICONS_MEDIA_FOLDER + "/");
		}

		private List<String> GetTitles(BingMapsAreaPart areaPart)
		{
			// Get titles
            // TODO: Would be nice to include these in the location object
			var titles = new List<String>();

			if(areaPart.BingMapsLocations != null)
			{
				foreach (var location in areaPart.BingMapsLocations)
				{
					titles.Add(_service.GetTitle(location, "Map {0}"));
				}
			}
			return titles;
		}
    }
}